/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package zombiedefense.framework;

import zombiedefense.ui.ZombieDefenseOverlay;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import zombiedefense.effects.Effect;
import zombiedefense.sprites.Player;
import zombiedefense.sprites.Zombie;
import zombiedefense.input.GameAction;
import zombiedefense.input.InputManager;
import zombiedefense.map.Camera;
import zombiedefense.map.PathFinder;
import zombiedefense.map.Raycaster;
import zombiedefense.map.TileMap;
import zombiedefense.sprites.Gun;
import zombiedefense.sprites.Sprite;
import zombiedefense.util.Timer;
import zombiedefense.util.Vector2D;

/**
 *
 * @author &{user}
 */
public class GamePlayState extends GameState{

    //constants
    private final double panSpeed = .01;
    private final int startHealth = 100;
    private final int startCash = 0;
    private final double movementSpeed = .004;
    private final double startx = .5;
    private final double starty = .5;
    
    //variables
    private boolean paused = false;
    private static TileMap map;
    private static PathFinder pathFinder;
    private static Raycaster rayCaster;
    private PlayerManager player;
    private ZombieManager zombies;
    private EffectManager effects;
    private ZombieDefenseOverlay overlay;
    
    //stats variables
    private int numFrames = 0;
    private final long statInterval = 1000;
    private Timer statTimer = new Timer(statInterval);
    
    //game actions
    private GameAction panleft = new GameAction("pan camera left");
    private GameAction panright = new GameAction("pan camera right");
    private GameAction panup = new GameAction("pan camera up");
    private GameAction pandown = new GameAction("pan camera down");
    private GameAction moveleft = new GameAction("move player left");
    private GameAction moveright = new GameAction("move player right");
    private GameAction moveup = new GameAction("move player up");
    private GameAction movedown = new GameAction("move player down");
    private GameAction fire = new GameAction("fire the current weapon");
    private GameAction weaponplus = new GameAction("change to next weapon",GameAction.DETECT_INITAL_PRESS_ONLY);
    private GameAction weaponminus = new GameAction("change to previous weapon",GameAction.DETECT_INITAL_PRESS_ONLY);
    private GameAction spawntest = new GameAction("spawn a zombie as a test",GameAction.DETECT_INITAL_PRESS_ONLY);
    private GameAction reload = new GameAction("reload the current gun",GameAction.DETECT_INITAL_PRESS_ONLY);
    
    public GamePlayState(Dimension gameDims, InputManager input,JPanel panel) {
	super(gameDims, input);
	
	//map controls
	input.mapToKey(panleft,KeyEvent.VK_LEFT);
	input.mapToKey(panright,KeyEvent.VK_RIGHT);
	input.mapToKey(panup,KeyEvent.VK_UP);
	input.mapToKey(pandown,KeyEvent.VK_DOWN);
	input.mapToKey(moveleft,KeyEvent.VK_A);
	input.mapToKey(moveright,KeyEvent.VK_D);
	input.mapToKey(moveup,KeyEvent.VK_W);
	input.mapToKey(movedown,KeyEvent.VK_S);
        input.mapToMouse(fire,InputManager.MOUSE_BUTTON_1);
	input.mapToKey(spawntest,KeyEvent.VK_ENTER);
	input.mapToKey(weaponplus,KeyEvent.VK_E);
	input.mapToMouse(weaponplus,InputManager.MOUSE_WHEEL_UP);
	input.mapToKey(weaponminus,KeyEvent.VK_Q);
	input.mapToMouse(weaponminus,InputManager.MOUSE_WHEEL_DOWN);
	input.mapToKey(reload,KeyEvent.VK_R);
        
	Player p = new Player(startx,starty,startHealth,startCash);
        
        //unlock the pistol for use in-game
        Gun.pistol.setLocked(false);
        p.setGun(Gun.pistol);
        p.giveCash(20000);
	
        //create map
	map = new TileMap(0,0,gameDims.width,gameDims.height,new Camera(0,0,p));
	map.load("map1.txt");
	map.centerCamera();
        
	//create object managers
	effects = new EffectManager(gameDims,map,input);
	player = new PlayerManager(gameDims,map,input,p);
	zombies = new ZombieManager(gameDims,map,input,effects,player);    //zombie manager needs to add text effects	
	
	//create pathfinder
	pathFinder = new PathFinder(map,player);
	
	//create raycaster
	rayCaster = new Raycaster(map,player,zombies);
        
        //create overlay
        overlay = new ZombieDefenseOverlay(panel,player.getPlayer(),zombies);
	
	//set up ray caster
	Sprite.setRaycaster(rayCaster);
	
	//set up pathfinder
	Sprite.setPathFinder(pathFinder);
	
	//set up effect manager
	Sprite.setEffectManager(effects);
	
	//set up player
	Effect.setPlayer(player);
    }
    
    public void update(long elapsedTime){
        
        paused = overlay.isUserPlaying();

        //do not update game state if paused
        if(paused)return;
     
	//check input - must be before update to satisfy button dependencies
	input();
	
	player.update(elapsedTime);
	zombies.update(elapsedTime);
	effects.update(elapsedTime);
	
	//center camera over player
	map.centerCamera();
	
	//pan camera and clip to screen
	map.update(elapsedTime);
        
        //find frame rate
        calcStats(elapsedTime);
        
        //update overlay
        overlay.update(elapsedTime);
    }
    
    public void draw(Graphics2D g){
	//draw map
	map.draw(g);
	
	//draw sprites
	player.draw(g);
	zombies.draw(g);
	effects.draw(g);
	
	//draw menus
        overlay.draw(g);
    }
    
    /**
     * Calculates the current framerate
     */
    private void calcStats(long elapsedTime){
	//check whether or not to recalc stats
	if(!statTimer.isStarted()){
	    statTimer.start();
	    statTimer.reset();
	}
	
	if(statTimer.hasTicked()){
	    overlay.setFps(((double)numFrames)/((double)statInterval) * 1000);	//divide #frames by #millisecs then convert to secs

	    numFrames = 0;     //reset counter
	    statTimer.reset(); //reset timer
	}else{
	    //update timer
	    statTimer.update(elapsedTime);

	    //count this frame
	    numFrames++;
	}
    }
    
    public void input(){
	Camera c = map.getCamera();
	
	if(panleft.isPressed() && panright.isPressed()){
	    c.dx = 0;
	}else if(panleft.isPressed()){
	    c.dx = -panSpeed;
	}else if(panright.isPressed()){
	    c.dx = panSpeed;
	}else{
	    c.dx = 0;
	}
	
	if(panup.isPressed() && pandown.isPressed()){
	    c.dy = 0;
	}else if(panup.isPressed()){
	    c.dy = -panSpeed;
	}else if(pandown.isPressed()){
	    c.dy = panSpeed;
	}else{
	    c.dy = 0;
	}
	
	Player p = player.getPlayer();
        Vector2D velocity = p.getVelocity();
	
	if(moveleft.isPressed() && moveright.isPressed()){
	    velocity.x = 0;
	}else if(moveleft.isPressed() && !(map.getScreenX(p.getX()) < 0)){
	    velocity.x = -movementSpeed;
	}else if(moveright.isPressed() && !(map.getScreenX(p.getX()) + p.getWidth() > gameDims.width)){
	    velocity.x = movementSpeed;
	}else{
	    velocity.x = 0;
	}
	
	if(moveup.isPressed() && movedown.isPressed()){
	    velocity.y = 0;
	}else if(moveup.isPressed() && !(map.getScreenY(p.getY()) < 0)){
	    velocity.y = -movementSpeed;
	}else if(movedown.isPressed() && !(map.getScreenY(p.getY()) + p.getHeight() > gameDims.height)){
	    velocity.y = movementSpeed;
	}else{
	    velocity.y = 0;
        }
        
        if (fire.isPressed()) {
	    //fire gun
	    player.getPlayer().shoot();
        }
	
	if(weaponplus.isPressed()){
	    player.getPlayer().nextGun();
	}else if(weaponminus.isPressed()){
	    player.getPlayer().previousGun();
	}
	
	if(spawntest.isPressed()){
	    //spawn a zombie
	    zombies.add(Zombie.createZombie(Zombie.ZombieType.basicZombie,8.0, 5.0));
	}
	
	if(reload.isPressed()){
	    player.getPlayer().reload();
	}
    }
}
